package com.service.socket.support;

import lombok.extern.slf4j.Slf4j;
import org.redisson.RedissonRedLock;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import javax.validation.constraints.NotNull;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <dl>
 * <dt>back-end</dt>
 * <dd>Description:</dd>
 * <dd>Copyright: Copyright (C) 2015</dd>
 * <dd>Company: </dd>
 * <dd>CreateDate: 2019年12月13日</dd>
 * </dl>
 *
 * @author
 */
@Slf4j
@Component
public class RedissonLockUtils {

    @Autowired
    @Qualifier("getRedisson")
    private RedissonClient redissonClient;

    private RedissonRedLock redissonRedLock;

    private Integer waitTime = 1;

    private Integer leaseTime = 3;

    public boolean lock(@NotNull String lockKey) {
        return lock(lockKey, waitTime, leaseTime);
    }

    public boolean lock(@NotNull String lockKey, Integer leaseTime) {
        return lock(lockKey, waitTime, leaseTime);
    }

    public boolean lock(@NotNull String lockKey, Integer waitTime, Integer leaseTime) {
        try {
            return redissonClient.getLock(lockKey).tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
            return false;
        }
    }

    public RedissonRedLock getRedLock(@NotNull String... lockKey) {
        RLock[] lockList = Arrays.stream(lockKey)
                .map(item -> redissonClient.getLock(item))
                .toArray(item -> new RLock[lockKey.length]);
        return new RedissonRedLock(lockList);
    }

    public RedissonRedLock getRedLock(List<String> lockKeyList) {
        RLock[] lockList = lockKeyList.stream()
                .map(item -> redissonClient.getLock(item))
                .toArray(item -> new RLock[lockKeyList.size()]);
        return new RedissonRedLock(lockList);
    }

    public boolean redLockTryLock(RedissonRedLock redLock) {
        try {
            return redLock.tryLock(waitTime, leaseTime, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
            return false;
        }
    }

    public void unlock(String lockKey) {
        try {
            redissonClient.getLock(lockKey).unlock();
            log.info("解锁成功<key:{}>", lockKey);
        } catch (Exception e) {
            log.info("解锁失败<key:{}>", lockKey);
            e.printStackTrace();
        }
    }

}
